import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Date;
import java.util.ArrayList;

import com.mysql.jdbc.PreparedStatement;

public class Asset {
	
	//Stand-alone attributes
	private int id;
	private String name;
	private String owner;
	private String custodian;
	private Date dateAcquired;
	private Date retentionPeriod;
	private String storageLocation;
	
	/*CodeDescriptionPairs
	private CodeDescriptionPair cdpType;
	private CodeDescriptionPair cdpClassification;
	private CodeDescriptionPair cdpMaintenanceSchedule;
	private CodeDescriptionPair cdpFinancial;
	private CodeDescriptionPair cdpConfidentiality;
	private CodeDescriptionPair cdpIntegrity;
	private CodeDescriptionPair cdpAvailability;
	/* */

	//Attributes with codes and descriptions
	private String availabilityCode;
	private String classificationCode;
	private String confidentialityCode;
	private String maintenanceScheduleCode;
	private String financialCode;
	private String integrityCode;
	private String typeCode;
	
	private String availabilityDesc;
	private String classificationDesc;
	private String confidentialityDesc;
	private String maintenanceScheduleDesc;
	private String financialDesc;
	private String integrityDesc;
	private String typeDesc;
	
	private boolean isDeleted = false;
	
	
	
	//This is private and only meant to be used by the static methods createAssetsFrom...
	private Asset(ResultSet rs){
	
		try {
			if(rs.next())
			{
				//Acquire the basic information
				id = rs.getInt("id");
				name = rs.getString("name");
				owner = rs.getString("owner");
				custodian = rs.getString("custodian");
				dateAcquired = rs.getDate("dateAcquired");
				retentionPeriod = rs.getDate("retentionPeriod");
				storageLocation = rs.getString("storageLocation");
				
				availabilityCode = rs.getString("availability");
				classificationCode = rs.getString("classification");
				confidentialityCode = rs.getString("confidentiality");
				maintenanceScheduleCode = rs.getString("maintenanceSchedule");
				financialCode = rs.getString("financial");
				integrityCode = rs.getString("integrity");
				typeCode = rs.getString("type");
				
				
				//Initialize the descriptions 
				initDescriptions();
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/*Static Methods*/
	
	//This is so we won't have to keep recoding the query and creation of asset objects if we wish to only have one.
	public static Asset createAssetFromID(int id){
		String query = "SELECT * FROM Asset WHERE id = "+id+";";
		Connection connection = DBConnector.getConnection();
		ResultSet rs = DBConnector.executeQuery(connection, query);
		
		Asset newAsset;
		if(rs == null)
			newAsset = null;
		else
			newAsset = new Asset(rs);
		
		try {
			connection.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
		return newAsset;
	}
	
	public static Asset createAssetFromIDTableDateTime(int ID, String tableName, String dateTime)
	{
		String query = "SELECT * FROM "+tableName+" WHERE ID = "+ID+" AND dateTime = \""+dateTime+"\";";
		Connection con = DBConnector.getConnection();
		ResultSet rs = DBConnector.executeQuery(con, query);
		
		Asset newAsset;
		if(rs == null)
			newAsset = null;
		else
			newAsset = new Asset(rs);
		
		try {
			con.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return newAsset;
	}
	
	//This will be used in add assets to insert a new asset into the database.
	public static int insertNewAssetIntoDBAndReturnNewID(String name, String owner, String custodian,String typeCode, Date dateAcquired, Date retentionPeriod, String maintenanceScheduleCode, String financialCode,  String confidentialityCode,  String integrityCode, String availabilityCode,  String classificationCode, String storageLocation)
	{
		Connection con = DBConnector.getConnection();
		String idQuery = "SELECT LAST_INSERT_ID()";
		String query;
		int id = -1;
		
		try {
			query = "INSERT into Asset(name, owner, custodian, type, dateAcquired, retentionPeriod, maintenanceSchedule, financial, confidentiality, integrity, availability, classification, storageLocation, isDeleted)" +
					"values(\""+name+"\", \""+owner+"\", \""+custodian+"\", \""+typeCode+"\", \""+dateAcquired+"\", \""+retentionPeriod+"\", \""+maintenanceScheduleCode+"\", \""+financialCode+"\", \""+confidentialityCode+"\", \""+integrityCode+"\", \""+availabilityCode+"\", \""+classificationCode+"\", \""+storageLocation+"\", 0)";
			
			DBConnector.executeUpdate(con, query);
			id = Integer.parseInt(DBConnector.executeQueryWithSingleValue(con, idQuery));
			con.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return id;
	}
		
	/*Regular Methods*/
	private String createDescriptionQuery(String tableName, String code)
	{
		return "SELECT Description FROM "+tableName+" WHERE code = '"+code+"';";
	}
	
	private String generateUpdateQuery(Asset a) {
		ArrayList<String> storage = new ArrayList<String>();
		String que = "UPDATE Asset SET ";
		
		if(!name.equals(a.getName())) 
			storage.add("name = \""+a.getName()+"\"");
		
		if(!owner.equals(a.getOwner())) 
			storage.add("owner = \""+a.getOwner()+"\"");
		
		if(!custodian.equals(a.getCustodian())) 
			storage.add("custodian = \""+a.getCustodian()+"\"");
		
		if(!storageLocation.equals(a.getStorageLocation()))
			storage.add("storageLocation = \""+a.getStorageLocation()+"\"");
		
		if(!dateAcquired.equals(a.getDateAcquired()))
			storage.add("dateAcquired =  \""+a.getDateAcquired()+"\"");
		
		if(!retentionPeriod.equals(a.getRetentionPeriod()))
			storage.add("retentionPeriod = \""+a.getRetentionPeriod()+"\"");
		
		if(!typeCode.equals(a.getTypeCode()))
			storage.add("Type = \""+a.getTypeCode()+"\"");
		
		if(!classificationCode.equals(a.getClassificationCode()))
			storage.add("Classification = \""+a.getClassificationCode()+"\"");
		
		if(!maintenanceScheduleCode.equals(a.getMaintenanceScheduleCode()))
			storage.add("maintenanceSchedule = \""+a.getMaintenanceScheduleCode()+"\"");
		
		if(!availabilityCode.equals(a.getAvailabilityCode()))
			storage.add("availability = \""+a.getAvailabilityCode()+"\"");
		
		if(!financialCode.equals(a.getFinancialCode()))
			storage.add("financial = \""+a.getFinancialCode()+"\"");
		
		if(!integrityCode.equals(a.getIntegrityCode()))
			storage.add("integrity = \""+a.getIntegrityCode()+"\"");
		
		if(!confidentialityCode.equals(a.getConfidentialityCode()))
			storage.add("confidentiality = \""+a.getConfidentialityCode()+"\"");

		for(int r = 0; r<storage.size(); r++){
			que += storage.get(r);
			if(r != storage.size() - 1)
				que += ", ";
		}
		
		que += " WHERE id = "+a.getId()+"";
		return que;
	}
	
	
	@Override public boolean equals(Object o)
	{
		Asset other = (Asset) o;
		
		if(!name.equals(other.getName()))
			return false;
	
		if(!owner.equals(other.getOwner())) 
			return false;
			
		if(!custodian.equals(other.getCustodian())) 
			return false;

		if(!storageLocation.equals(other.getStorageLocation()))
			return false;
		
		if(!dateAcquired.equals(other.getDateAcquired()))
			return false;
		
		if(!retentionPeriod.equals(other.getRetentionPeriod()))
			return false;
		
		if(!typeCode.equals(other.getTypeCode()))
			return false;
		
		if(!classificationCode.equals(other.getClassificationCode()))
			return false;
		
		if(!maintenanceScheduleCode.equals(other.getMaintenanceScheduleCode()))
			return false;
		
		if(!availabilityCode.equals(other.getAvailabilityCode()))
			return false;
		
		if(!financialCode.equals(other.getFinancialCode()))
			return false;
		
		if(!integrityCode.equals(other.getIntegrityCode()))
			return false;
		
		if(!confidentialityCode.equals(other.getConfidentialityCode()))
			return false;
		
		return true;
	}
	
	public Asset getCopy()
	{
		Asset copy = createAssetFromID(id);
		
		copy.setName(name);
		copy.setOwner(owner);
		copy.setCustodian(custodian);
		copy.setStorageLocation(storageLocation);
		
		copy.setDateAcquired(dateAcquired);
		copy.setRetentionPeriod(retentionPeriod);
		
		copy.setTypeCode(typeCode);
		copy.setClassificationCode(classificationCode);
		copy.setMaintenanceScheduleCode(maintenanceScheduleCode);
		copy.setAvailabilityCode(availabilityCode);
		copy.setFinancialCode(financialCode);
		copy.setIntegrityCode(integrityCode);
		copy.setAvailabilityCode(availabilityCode);
		
		return copy;
	}
	
	public void initDescriptions()
	{
		Connection connection = DBConnector.getConnection();
		availabilityDesc = DBConnector.executeQueryWithSingleValue(connection, createDescriptionQuery("availabilityValues", availabilityCode));
		classificationDesc = DBConnector.executeQueryWithSingleValue(connection, createDescriptionQuery("assetClassifications", classificationCode));
		confidentialityDesc = DBConnector.executeQueryWithSingleValue(connection, createDescriptionQuery("confidentialityValues", confidentialityCode));
		maintenanceScheduleDesc = DBConnector.executeQueryWithSingleValue(connection, createDescriptionQuery("maintenanceSchedules", maintenanceScheduleCode));
		financialDesc = DBConnector.executeQueryWithSingleValue(connection, createDescriptionQuery("financialValues", financialCode));
		integrityDesc = DBConnector.executeQueryWithSingleValue(connection, createDescriptionQuery("integrityValues", integrityCode));
		typeDesc = DBConnector.executeQueryWithSingleValue(connection, createDescriptionQuery("assetTypes", typeCode));
		
		try {
			connection.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void updateSelfInDB(Asset editedVersion)
	{
		LogMethods log = new LogMethods();
		String query = generateUpdateQuery(editedVersion);
		Connection con = DBConnector.getConnection();	
		DBConnector.executeUpdate(con, query);
		log.EditLog(editedVersion);
		try {
			con.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
	}
	
	public void deleteSelfInDB(Asset theAsset)
	{
		LogMethods log = new LogMethods();
		Connection con = DBConnector.getConnection();
		String query = "UPDATE Asset set isDeleted = 1 WHERE id = "+id+";";
		DBConnector.executeUpdate(con, query);
		log.DeleteLog(theAsset);
		try {
			con.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
	}
	
	/* Auto-Generated Getters and Setters*/

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getOwner() {
		return owner;
	}

	public void setOwner(String owner) {
		this.owner = owner;
	}

	public String getCustodian() {
		return custodian;
	}

	public void setCustodian(String custodian) {
		this.custodian = custodian;
	}

	public Date getDateAcquired() {
		return dateAcquired;
	}

	public void setDateAcquired(Date dateAcquired) {
		this.dateAcquired = dateAcquired;
	}

	public Date getRetentionPeriod() {
		return retentionPeriod;
	}

	public void setRetentionPeriod(Date retentionPeriod) {
		this.retentionPeriod = retentionPeriod;
	}

	public String getStorageLocation() {
		return storageLocation;
	}

	public void setStorageLocation(String storageLocation) {
		this.storageLocation = storageLocation;
	}

	public String getAvailabilityCode() {
		return availabilityCode;
	}

	public void setAvailabilityCode(String availabilityCode) {
		this.availabilityCode = availabilityCode;
	}

	public String getClassificationCode() {
		return classificationCode;
	}

	public void setClassificationCode(String classificationCode) {
		this.classificationCode = classificationCode;
	}

	public String getConfidentialityCode() {
		return confidentialityCode;
	}

	public void setConfidentialityCode(String confidentialityCode) {
		this.confidentialityCode = confidentialityCode;
	}

	public String getMaintenanceScheduleCode() {
		return maintenanceScheduleCode;
	}

	public void setMaintenanceScheduleCode(String maintenanceScheduleCode) {
		this.maintenanceScheduleCode = maintenanceScheduleCode;
	}

	public String getFinancialCode() {
		return financialCode;
	}

	public void setFinancialCode(String financialCode) {
		this.financialCode = financialCode;
	}

	public String getIntegrityCode() {
		return integrityCode;
	}

	public void setIntegrityCode(String integrityCode) {
		this.integrityCode = integrityCode;
	}

	public String getTypeCode() {
		return typeCode;
	}

	public void setTypeCode(String typeCode) {
		this.typeCode = typeCode;
	}

	public int getId() {
		return id;
	}

	public String getAvailabilityDesc() {
		return availabilityDesc;
	}

	public String getClassificationDesc() {
		return classificationDesc;
	}

	public String getConfidentialityDesc() {
		return confidentialityDesc;
	}

	public String getMaintenanceScheduleDesc() {
		return maintenanceScheduleDesc;
	}

	public String getFinancialDesc() {
		return financialDesc;
	}

	public String getIntegrityDesc() {
		return integrityDesc;
	}

	public String getTypeDesc() {
		return typeDesc;
	}
}
